﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Glue.Internals
{
    internal partial class ObjectMemberFactory
    {
        private class DictionaryMember: EnumerableMember
        {
            public DictionaryMember(IObjectMemberAccessor accessor):base(accessor)
            {
                if (!MemberType.IsOfInterfaceType(typeof(IDictionary<,>)))
                    throw new GlueException("DictionaryMember has to be an IDictionary Type. Is: " + MemberType.Name);
                ConcreteDictionaryTypesMustInheritUnGenericIDictionary();
            }

            private void ConcreteDictionaryTypesMustInheritUnGenericIDictionary()
            {
                if (!MemberType.IsInterface && !MemberType.IsOfInterfaceType(typeof(IDictionary)))
                {
                    throw new GlueException(
                        "Custom Dictionary types must inherit IDictionary (Not the generic version). So must the type: " +
                        MemberType.GetReadableName());
                }
            }

            public override IGlueCollection CreateCollection(IGlueCollection collection)
            {
                return new SetterDictionaryCollection(GenerateDictionary(), this);
            }

            private IDictionary GenerateDictionary()
            {
                if (MemberType.IsInterface)
                {
                    var genericArgument = MemberType.GetGenericArguments();
                    Type destDictionaryType = typeof(Dictionary<,>).MakeGenericType(genericArgument[0], genericArgument[1]);
                    return (IDictionary)destDictionaryType.CreateInstance();
                }
                return (IDictionary)MemberType.CreateInstance();
                
            }

            public override Type GetElementType()
            {
                //var genericArgument = MemberType.GetGenericArguments();
                //return typeof(KeyValuePair<,>).MakeGenericType(genericArgument[0],genericArgument[1]);

                // TODO: This is a bug
                return MemberType.GetGenericArguments()[1];
            }

            private class SetterDictionaryCollection : ISetterCollection
            {
                private readonly IDictionary dictionary;
                private readonly EnumerableMember creator;

                public SetterDictionaryCollection(IDictionary dictionary, EnumerableMember creator)
                {
                    this.dictionary = dictionary;
                    this.creator = creator;
                }

                public bool MoveNext() { throw new GlueException("System error: A SetterDictionaryCollection is trying to do Getter-stuff"); }
                public object Current { get { throw new GlueException("System error: A SetterDictionaryCollection is trying to do Getter-stuff"); } }
                public int Count { get { throw new GlueException("System error: A SetterDictionaryCollection is trying to do Getter-stuff"); } }

                public void Add(object value)
                {
                    // TODO: Consider performance on this one... 
                    var key = value.GetType().GetProperty("Key").GetValue(value, new object[0]);
                    var actualValue = value.GetType().GetProperty("Value").GetValue(value, new object[0]);
                    dictionary.Add(key, actualValue);
                }

                public bool CreatedBy(ICollectionMember collectionMember)
                {
                    return collectionMember == creator;
                }

                public object GetList()
                {
                    return dictionary;
                }
            }
        }
    }
}
